-module(proto).

-include("common.hrl").

-export([encode/1,decode/1]).
-export([decode2/1]).

%%===========================EXPORTED FUNCTION==============================
encode(Record)->
	try
		RecName = element(1, Record),
		Bin = proto_struct:encode_def(RecName, Record),
		MsgID = proto_struct:get_id(RecName),
		Bin2 = [MsgID, Bin],
		ByteSize = length(Bin2) + 5,
		FinalBin = if ByteSize > 409600 ->
			Bin3 = zlib:compress(Bin2),
			?ERR("compress data Record=~p", [Record]),
			[1, Bin3];
			           true ->
				           [0, Bin2]
		           end,
		mochijson2:encode(FinalBin)
	catch
		Reason:Why:Stack ->
			?ERR("encode Reason=~p,Why=~p,Stack=~p,Record=~p", [Reason, Why, Stack, Record])
	end.

decode(Json) ->
	try
		DataList = mochijson2:decode(Json),
%%	IsCompressed = hd(DataList),%%客户端发来的信息基本不会压缩，因为数据都不大
		decode2(DataList)
	catch
		Reason:Why:Stack ->
			?ERR("decode Reason=~p,Why=~p,Stack=~p,Json=~p", [Reason, Why, Stack, Json])
	end.

%%===========================LOCAL FUNCTION==============================
decode2([ID|T]) ->
	[RecName|TypeList] = proto_struct:decode_def(ID),
	%% 剩余字节严格匹配，不隐藏前端多发字节的错误
	{ok, [], Result} = decode3(TypeList, T, [RecName]),
	list_to_tuple(Result).

decode3([{list,Type}|TypeList],[VList|T], Result) ->
	ChildTypeList = lists:duplicate(length(VList), Type),
	{ok, [], List} = decode3(ChildTypeList, VList, []),
	decode3(TypeList, T, [List|Result]);
decode3([{string,FieldName}|TypeList],[V|T],Result)when is_atom(FieldName)->
	decode3(TypeList, T, [util:term_to_list(V)|Result]);
decode3([FieldName|TypeList],[V|T],Result)when is_atom(FieldName)->
	decode3(TypeList, T, [V|Result]);
decode3([MsgID|TypeList],[V|T],Result)when is_integer(MsgID) ->
	[RecName|ChildTypeList] = proto_struct:decode_def(MsgID),
	{ok, [], ChildVal}=decode3(ChildTypeList, V, [RecName]),
	decode3(TypeList, T, [list_to_tuple(ChildVal)|Result]);
decode3([],Bin,Result) ->
	{ok, Bin, lists:reverse(Result)}.